package plp.funcoo.expressions;

import plp.funcoo.environment.compilation.CompilationEnvironment;
import plp.funcoo.environment.execution.ExecutionContext;
import plp.funcoo.environment.execution.ExecutionEnvironment;
import plp.funcoo.exceptions.ClassNotDeclared;
import plp.funcoo.exceptions.MethodAlreadDeclared;
import plp.funcoo.exceptions.MethodNotDeclared;
import plp.funcoo.exceptions.VarAlreadyDeclared;
import plp.funcoo.exceptions.VarNotDeclared;
import plp.funcoo.value.BooleanValue;
import plp.funcoo.value.Value;

/**
 * Um objeto desta classe representa uma Expressao de Igualdade entre 
 * Expressoes cuja avaliacao resulta num mesmo valor primitivo.
 */
public class ExpEquals extends TestingExpression{

	/**
	 * Constroi uma Expressao de Igualdade com as sub-expressoes especificadas.
	 * Assume-se que estas sub-expressoes resultam num mesmo valor primitivo
	 * quando avaliadas.
	 * @param esq Expressao da esquerda
	 * @param dir Expressao da direita
	 */
	public ExpEquals(Expression left, Expression right){
		super(left, right, "==");
	}
	@Override
	public ExecutionEnvironment evaluate(ExecutionEnvironment envi) throws VarNotDeclared, MethodNotDeclared, VarAlreadyDeclared, MethodAlreadDeclared {
		envi = getLeft().evaluate(envi); 
		Value l =  ((ExecutionContext) envi).getValueAnalyzed();
		envi = getRight().evaluate(envi); 
		Value r =  ((ExecutionContext) envi).getValueAnalyzed();
		((ExecutionContext) envi).setValueAnalyzed(new BooleanValue( l.getValue() == r.getValue() ));
		return envi;
		
	}

	@Override
	protected boolean checkTypeTerminal(CompilationEnvironment envi)
			throws VarNotDeclared, ClassNotDeclared {
		return getLeft().getType(envi).equals(getRight().getType(envi));
	}
	@Override
	public Expression makeCopy() {
		return new ExpEquals(this.getLeft().makeCopy(), this.getRight().makeCopy());
	}
}
